package com.bank.config;

import cn.dev33.satoken.exception.NotLoginException;
import com.alibaba.fastjson.JSONException;
import com.bank.common.exception.ErrorCode;
import com.bank.common.exception.GlobalException;
import com.bank.common.io.RestVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpMediaTypeNotAcceptableException;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import org.springframework.web.servlet.NoHandlerFoundException;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.text.ParseException;
import java.util.Iterator;
import java.util.Set;
import java.util.regex.PatternSyntaxException;

/**
 * 异常全局处理
 *
 * @author Fu Zhaohui
 * @date 2016/1/14 0014
 */
@Slf4j
@ControllerAdvice
public class ExceptionHandlerAdvice {

    @ExceptionHandler(value = Exception.class)
    @ResponseStatus(HttpStatus.OK)
    @ResponseBody
    public RestVo serverException(Exception e) {
        RestVo result = new RestVo();
        result.setServerException("系统繁忙，请稍后重试〜");
        log.error("系统异常:  {}",e.getMessage(), e);
        return result;
    }

    @ExceptionHandler(NoHandlerFoundException.class)
    @ResponseStatus(value = HttpStatus.NOT_FOUND)
    @ResponseBody
    public RestVo requestHandlingNoHandlerFound() {
        RestVo result = new RestVo();
        result.setNotFoundException("服务未发现");
        return result;
    }



    @ExceptionHandler(value = JSONException.class)
    @ResponseStatus(HttpStatus.OK)
    @ResponseBody
    public RestVo jsonResponse(JSONException je) {
        log.error("数据格式异常:   {}",je.getMessage(), je);
        RestVo result = new RestVo();
        result.setCommonException("数据格式异常");
        return result;
    }

    @ExceptionHandler(value = HttpMessageNotWritableException.class)
    @ResponseStatus(HttpStatus.OK)
    @ResponseBody
    public RestVo notWritableResponse(HttpMessageNotWritableException we) {
        log.error("HttpMessage异常:   {}",we.getMessage(), we);
        RestVo result = new RestVo();
        result.setCommonException("HttpMessage异常");
        return result;
    }

    @ExceptionHandler(value = HttpMediaTypeNotAcceptableException.class)
    @ResponseStatus(HttpStatus.OK)
    @ResponseBody
    public RestVo mediaTypeResponse(HttpMediaTypeNotAcceptableException htae) {
        RestVo result = new RestVo();
        result.setCommonException(htae.getMessage());
        return result;
    }

    @ExceptionHandler(value = DuplicateKeyException.class)
    @ResponseStatus(HttpStatus.OK)
    @ResponseBody
    public RestVo mediaTypeResponse(DuplicateKeyException dke) {
        log.error("数据重复：  {}",dke.getMessage(), dke);
        RestVo result = new RestVo();
        result.setCommonException("数据已存在");
        return result;
    }


    @ExceptionHandler(value = GlobalException.class)
    @ResponseStatus(HttpStatus.OK)
    @ResponseBody
    public RestVo mediaTypeResponse(GlobalException dke) {
        log.error("GlobalException:  {}",dke.getMessage(), dke);
        return new RestVo(dke.getCode(), dke.getMessage());
    }



    @ExceptionHandler(value = ParseException.class)
    @ResponseStatus(HttpStatus.OK)
    @ResponseBody
    public RestVo parseResponse(ParseException pe) {
        RestVo result = new RestVo();
        result.setCommonException("日期格式错误 " + pe.getMessage());
        return result;
    }

    @ExceptionHandler(value = HttpRequestMethodNotSupportedException.class)
    @ResponseStatus(HttpStatus.OK)
    @ResponseBody
    public RestVo supportResponse(HttpRequestMethodNotSupportedException se) {
        RestVo result = new RestVo();
        result.setCommonException(se.getMessage());
        return result;
    }

    @ExceptionHandler(value = HttpMediaTypeNotSupportedException.class)
    @ResponseStatus(HttpStatus.OK)
    @ResponseBody
    public RestVo mediaTypeResponse(HttpMediaTypeNotSupportedException me) {
        RestVo result = new RestVo();
        result.setCommonException(me.getMessage());
        return result;
    }

    @ExceptionHandler(value = HttpMessageNotReadableException.class)
    @ResponseStatus(HttpStatus.OK)
    @ResponseBody
    public RestVo supportResponse(HttpMessageNotReadableException se) {
        RestVo result = new RestVo();
        result.setCommonException(se.getMessage());
        return result;
    }

    @ExceptionHandler(value = MissingServletRequestParameterException.class)
    @ResponseStatus(HttpStatus.OK)
    @ResponseBody
    public RestVo supportResponse(MissingServletRequestParameterException me) {
        RestVo result = new RestVo();
        result.setCommonException(me.getMessage());
        return result;
    }

    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.OK)
    @ResponseBody
    public RestVo supportResponse(MethodArgumentNotValidException me) {
        RestVo result = new RestVo();
        FieldError error = me.getBindingResult().getFieldError();
        result.setCommonException(error.getDefaultMessage());
        return result;
    }



    @ExceptionHandler
    @ResponseStatus(HttpStatus.OK)
    @ResponseBody
    public RestVo numberException(NumberFormatException ne) {
        log.error("数据类型异常", ne);
        RestVo result = new RestVo();
        result.setCommonException("数据类型异常:  {}" + ne.getMessage());
        return result;
    }

    @ExceptionHandler
    @ResponseStatus(HttpStatus.OK)
    @ResponseBody
    public RestVo patternException(PatternSyntaxException pe) {
        log.error("参数异常", pe);
        RestVo result = new RestVo();
        result.setCommonException("参数异常:  {}" + pe.getMessage());
        return result;
    }


    @ExceptionHandler(MethodArgumentTypeMismatchException.class)
    @ResponseStatus(HttpStatus.OK)
    @ResponseBody
    public RestVo argsException(MethodArgumentTypeMismatchException ae) {
        log.error("参数类型异常", ae);
        RestVo result = new RestVo();
        result.setCommonException("参数类型异常:  {}" + ae.getMessage());
        return result;
    }
    @ExceptionHandler(NotLoginException.class)
    @ResponseStatus(HttpStatus.OK)
    @ResponseBody
    public RestVo argsException(NotLoginException ae) {
        log.error("登录异常", ae);
        RestVo result = new RestVo();
        result.setCode(ErrorCode.LOGIN.getErrCode());
        result.setResult(ae.getType());
        result.setMsg(ae.getMessage());
        return result;
    }


    @ExceptionHandler
    @ResponseStatus(HttpStatus.OK)
    @ResponseBody
    public RestVo handle(ConstraintViolationException ce) {
        RestVo result = new RestVo();
        Set<ConstraintViolation<?>> violations = ce.getConstraintViolations();
        StringBuilder message = new StringBuilder();
        for (Iterator<ConstraintViolation<?>> iterator = violations.iterator(); iterator.hasNext(); ) {
            ConstraintViolation violation = iterator.next();
            message.append(violation.getMessage());
        }
        result.setCommonException(message.toString());
        return result;
    }



}
